package edu.ccut.titan.tag.report.servlet;

import java.awt.Color;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import net.sf.jasperreports.crosstabs.fill.calculation.BucketDefinition;
import net.sf.jasperreports.charts.design.JRDesignBarPlot;
import net.sf.jasperreports.crosstabs.JRCellContents;
import net.sf.jasperreports.crosstabs.JRCrosstabColumnGroup;
import net.sf.jasperreports.crosstabs.JRCrosstabRowGroup;
import net.sf.jasperreports.crosstabs.design.JRDesignCellContents;
import net.sf.jasperreports.crosstabs.design.JRDesignCrosstab;
import net.sf.jasperreports.crosstabs.design.JRDesignCrosstabBucket;
import net.sf.jasperreports.crosstabs.design.JRDesignCrosstabCell;
import net.sf.jasperreports.crosstabs.design.JRDesignCrosstabColumnGroup;
import net.sf.jasperreports.crosstabs.design.JRDesignCrosstabGroup;
import net.sf.jasperreports.crosstabs.design.JRDesignCrosstabMeasure;
import net.sf.jasperreports.crosstabs.design.JRDesignCrosstabRowGroup;
import net.sf.jasperreports.crosstabs.fill.calculation.BucketDefinition;
import net.sf.jasperreports.crosstabs.fill.calculation.BucketDefinition.Bucket;
import net.sf.jasperreports.engine.JRAlignment;
import net.sf.jasperreports.engine.JRBox;
import net.sf.jasperreports.engine.JRElement;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRLine;
import net.sf.jasperreports.engine.JRLineBox;
import net.sf.jasperreports.engine.JRStyle;
import net.sf.jasperreports.engine.design.JRDesignBand;
import net.sf.jasperreports.engine.design.JRDesignChart;
import net.sf.jasperreports.engine.design.JRDesignExpression;
import net.sf.jasperreports.engine.design.JRDesignField;
import net.sf.jasperreports.engine.design.JRDesignLine;
import net.sf.jasperreports.engine.design.JRDesignStaticText;
import net.sf.jasperreports.engine.design.JRDesignStyle;
import net.sf.jasperreports.engine.design.JRDesignTextField;
import net.sf.jasperreports.engine.design.JasperDesign;
import net.sf.jasperreports.engine.util.JRColorUtil;
import net.sf.jasperreports.engine.xml.JRXmlLoader;
import edu.ccut.titan.tag.report.chart.ITitanChartDataset;
import edu.ccut.titan.tag.report.chart.IType;
import edu.ccut.titan.tag.report.chart.TitanChartDataset;
import edu.ccut.titan.tag.report.chart.Type;
import edu.ccut.titan.tag.report.design.CellInfo;
import edu.ccut.titan.tag.report.design.ChartsInfo;
import edu.ccut.titan.tag.report.design.ColumnGroupInfo;
import edu.ccut.titan.tag.report.design.CrosstabInfo;
import edu.ccut.titan.tag.report.design.FooterInfo;
import edu.ccut.titan.tag.report.design.HeaderInfo;
import edu.ccut.titan.tag.report.design.MeasureInfo;
import edu.ccut.titan.tag.report.design.ReportDesignInfo;
import edu.ccut.titan.tag.report.design.ReportFieldInfo;
import edu.ccut.titan.tag.report.design.RowGroupInfo;

public class TitanReportDesigner {
	private static final String FONT_ITALIC = "italic";

	private static final String FONT_BLOD = "blod";
	private boolean isCrosstab;
	private int crosstabWidth;
	private String sortField;
	private String sort;
	private String reportType;
	private static final float LINE_BORDER = 0.5F;

	private static final String DEFAULT_DESIGN_TEMPLETE_PATH = "dynamicReport.jrxml";

	public final static String FIELD_KEY_DEFAULT_VALUE = "no key";
	public final static String FIELD_TITLE_DEFAULT_VALUE = "Title";
	public final static String FIELD_WIDTH_DEFAULT_VALUE = "50";

	public final static String CACHE_KEY = "CACHE_KEY";

	private final static JRDesignStyle normalStyle = new JRDesignStyle();

	private final static JRDesignStyle boldStyle = new JRDesignStyle();

	private final static JRDesignStyle italicStyle = new JRDesignStyle();

	private static TitanReportDesigner instance = new TitanReportDesigner();

	private TitanReportDesigner() {

	}

	public static TitanReportDesigner getInstance() {
		return instance;
	}

	public JasperDesign getReportDesign(ReportDesignInfo config) {
		return this.getReportDesign(config, null, 0, "html");
	}

	public JasperDesign getReportDesign(ReportDesignInfo config,
			String templetePath, int pageWidth, String reportType) {
		crosstabWidth = pageWidth - 50;
		this.reportType = reportType;
		JasperDesign design = null;
		try {
			if (templetePath != null) {
				design = JRXmlLoader.load(JasperDesign.class
						.getResourceAsStream(templetePath));
			} else {
				design = JRXmlLoader.load(TitanReportDesigner.class
						.getResourceAsStream(DEFAULT_DESIGN_TEMPLETE_PATH));
			}
			if (!"".equals(config.getSort()))
				sort = config.getSort();
			else
				sort = null;
			if (!"".equals(config.getSortField()))
				sortField = config.getSortField();
			else
				sortField = null;
			if (design != null) {
				this.initalDesignByConfig(design, config);
			}
		} catch (JRException e) {
			e.printStackTrace();
		}
		return design;
	}

	public void initalDesignByConfig(JasperDesign design,
			ReportDesignInfo config) throws JRException {
		this.initalDesignStyle(design, config);
		this.initalDesignParameter(design, config);
		this.initalDesignBackground(design, config);
		this.initalDesignTitle(design, config);
		this.initalDesignPageHeader(design, config);
		this.initalDesignColumnHeaderAndDetail(design, config);
		this.initalDesignPageFooter(design, config);
		this.initalDesignLastPageFooter(design, config);
		this.initalDesignColumnFooter(design, config);
		this.initalDesignSummary(design, config);
	}

	private void initalDesignLastPageFooter(JasperDesign design,
			ReportDesignInfo config) {
		List<FooterInfo> footerInfos = config.getFooterInfos();
		int x = 0;
		JRDesignBand lastPageFooterBand = new JRDesignBand();
		lastPageFooterBand.setSplitAllowed(true);
		lastPageFooterBand.setHeight(30);
		// lastPageFooterBand.setSplitAllowed(true);
		for (FooterInfo footerInfo : footerInfos) {
			x += Integer.parseInt(footerInfo.getWidth());
			JRDesignStaticText designStaticText = new JRDesignStaticText();
			designStaticText.setStyle(normalStyle);
			designStaticText
					.setHorizontalAlignment(JRAlignment.HORIZONTAL_ALIGN_JUSTIFIED);
			designStaticText.setText(footerInfo.getTitle() + ":"
					+ footerInfo.getValue());
			if (!"".equals(footerInfo.getHeight())
					&& footerInfo.getHeight() != null) {
				designStaticText.setHeight(Integer.parseInt(footerInfo
						.getHeight()));
			} else {
				designStaticText.setHeight(0);
			}
			designStaticText.setX(x - Integer.parseInt(footerInfo.getWidth()));
			
			if ("excel".equals(reportType)){
				designStaticText.setY(Integer.MIN_VALUE);
			}
			else {
				designStaticText.setY(0);
			}
			
			designStaticText.setFontSize(12);
			designStaticText.setWidth(Integer.parseInt(footerInfo.getWidth()));
			lastPageFooterBand.addElement(designStaticText);
		}
		design.setLastPageFooter(lastPageFooterBand);
	}

	private void initalDesignStyle(JasperDesign design, ReportDesignInfo config)
			throws JRException {
		normalStyle.setName("SongTi_Normal");
		// normalStyle.setDefault(true);
		normalStyle.setFontName("宋体");
		normalStyle.setFontSize(12);
		normalStyle.setPdfFontName("STSong-Light");
		normalStyle.setPdfEncoding("UniGB-UCS2-H");
		normalStyle.setPdfEmbedded(true);
		design.addStyle(normalStyle);

		boldStyle.setName("SongTi_Bold");
		boldStyle.setFontName("宋体");
		boldStyle.setFontSize(12);
		boldStyle.setBold(true);
		boldStyle.setPdfFontName("STSong-Light");
		boldStyle.setPdfEncoding("UniGB-UCS2-H");
		boldStyle.setPdfEmbedded(true);
		design.addStyle(boldStyle);

		italicStyle.setName("SongTi_Italic");
		italicStyle.setFontName("宋体");
		italicStyle.setFontSize(12);
		italicStyle.setItalic(true);
		italicStyle.setPdfFontName("STSong-Light");
		italicStyle.setPdfEncoding("UniGB-UCS2-H");
		italicStyle.setPdfEmbedded(true);
		design.addStyle(italicStyle);
	}

	private void initalDesignParameter(JasperDesign design,
			ReportDesignInfo config) throws JRException {
	}

	private void initalDesignBackground(JasperDesign design,
			ReportDesignInfo config) throws JRException {

	}

	private void initalDesignTitle(JasperDesign design, ReportDesignInfo config)
			throws JRException {

		JRDesignBand titleBand = new JRDesignBand();
		titleBand.setHeight(50);

		// JRDesignLine line = new JRDesignLine();
		// line.setX(0);
		// line.setY(0);
		// line.setWidth(595);
		// line.setHeight(30);
		// titleBand.addElement(line);

		JRDesignStaticText title = new JRDesignStaticText();
		title.setStyle(boldStyle);

		if ("".equals(config.getTitle()))
			title.setText("报表的标题");
		else
			title.setText(config.getTitle());

		if ("excel".equals(reportType))
			title.setWidth(500);
		else
			title.setWidth(crosstabWidth - 10);
		title.setHeight(50);
		title.setFontSize(22);
		title.setHorizontalAlignment(JRAlignment.HORIZONTAL_ALIGN_CENTER);
		titleBand.addElement(title);

		// JRDesignTextField textField = new JRDesignTextField();
		// textField.setBlankWhenNull(true);
		// textField.setX(0);
		// textField.setY(10);
		// textField.setWidth(595);
		// textField.setHeight(30);
		// textField.setHorizontalAlignment(JRAlignment.HORIZONTAL_ALIGN_CENTER);
		// textField.setStyle(normalStyle);
		// textField.setFontSize(22);
		//
		// JRDesignExpression expression = new JRDesignExpression();
		// expression.setValueClass(java.lang.String.class);
		// expression.setText("$P{title} != null ? $P{title} : \"报表的标题\"");
		// textField.setExpression(expression);
		// titleBand.addElement(textField);

		design.setTitle(titleBand);
	}

	private void initalDesignPageHeader(JasperDesign design,
			ReportDesignInfo config) throws JRException {

		JRDesignBand pageHeaderBand = new JRDesignBand();

		List<HeaderInfo> headerInfos = config.getHeaderInfos();
		int x = 0;
		int height = 0;
		Map<String, String> heightset = new HashMap<String, String>();
		for (HeaderInfo headerInfo : headerInfos) {

			// key
			JRDesignStaticText designStaticText = new JRDesignStaticText();
			int titleWidth = 0;
			if ("excel".equals(reportType))
				titleWidth = headerInfo.getTitle().length() * 30;
			else
				titleWidth = headerInfo.getTitle().length() * 22;// getWidth(headerInfo.getTitle());
			designStaticText.setStyle(boldStyle);
			designStaticText
					.setHorizontalAlignment(JRAlignment.HORIZONTAL_ALIGN_JUSTIFIED);
			designStaticText.setText(headerInfo.getTitle() + ":");
			if (!"".equals(headerInfo.getHeight())
					&& headerInfo.getHeight() != null) {
				designStaticText.setHeight(height = Integer.parseInt(headerInfo
						.getHeight()));
			} else {
				designStaticText.setHeight(0);
			}
			heightset.put(headerInfo.getY(), "");
			// int y = Integer.parseInt(headerInfo.getY());

			if (Integer.parseInt(headerInfo.getX()) == 0
					&& Integer.parseInt(headerInfo.getY()) == 0) {
				x += titleWidth;
				designStaticText.setX(x - titleWidth);
				designStaticText.setY(0);
			} else {
				designStaticText.setX(Integer.parseInt(headerInfo.getX()));
				designStaticText.setY(Integer.parseInt(headerInfo.getY()));
			}
			designStaticText.setFontSize(14);
			designStaticText.setWidth(titleWidth);
			pageHeaderBand.addElement(designStaticText);

			// value
			JRDesignStaticText designStaticTextValue = new JRDesignStaticText();
			int valueWidth = 0;
			if ("excel".equals(reportType))
				valueWidth = getExcelWidth(headerInfo.getValue());
			else
				valueWidth = getWidth(headerInfo.getValue());// getWidth(headerInfo.getValue());
			designStaticTextValue.setStyle(normalStyle);
			designStaticTextValue
					.setHorizontalAlignment(JRAlignment.HORIZONTAL_ALIGN_JUSTIFIED);
			designStaticTextValue.setText(headerInfo.getValue());
			if (!"".equals(headerInfo.getHeight())
					&& headerInfo.getHeight() != null) {
				designStaticTextValue.setHeight(height = Integer
						.parseInt(headerInfo.getHeight()));
			} else {
				designStaticTextValue.setHeight(0);
			}
			heightset.put(headerInfo.getY(), "");

			if (Integer.parseInt(headerInfo.getX()) == 0
					&& Integer.parseInt(headerInfo.getY()) == 0) {
				x += valueWidth;
				designStaticTextValue.setX(x - valueWidth);
				designStaticTextValue.setY(0);
			} else {
				designStaticTextValue.setX(Integer.parseInt(headerInfo.getX())
						+ titleWidth);
				designStaticTextValue.setY(Integer.parseInt(headerInfo.getY()));
			}
			designStaticTextValue.setFontSize(14);
			designStaticTextValue.setWidth(valueWidth);
			pageHeaderBand.addElement(designStaticTextValue);

		}
		Set<String> keys = heightset.keySet();
		keys.size();
		for (String key : keys) {
			height += Integer.parseInt(key);
		}
		pageHeaderBand.setHeight(height);
		design.setPageHeader(pageHeaderBand);

	}

	public int getWidth(String str) {
		int count = 0; // 定义一个boolean值，用来表示是否包含数字
		for (int i = 0; i < str.length(); i++) { // 循环遍历字符串
			if (Character.isDigit(str.charAt(i))) { // 用char包装类中的判断数字的方法判断每一个字符
				count += 1;
			}
		}
		int width = count * 9 + (str.length() - count) * 18;

		return width;
	}

	public int getExcelWidth(String str) {
		
		//int width = str.length() * 30 ;
		int width = 0;
		char[] strArray = str.toCharArray();
		
		for(int i = 0, n = strArray.length; i < n; i++){
			if(strArray[i] <= 'z'){
				width += 10;
			} else {
				width += 20;
			}
		}
		return width;
	}

	public static void main(String args[]) {
		int isNumber = 0; // 定义一个boolean值，用来表示是否包含数字
		String str = "aaasss8f4ff"; // 假设有一个字符串
		for (int i = 0; i < str.length(); i++) { // 循环遍历字符串
			if (Character.isDigit(str.charAt(i))) { // 用char包装类中的判断数字的方法判断每一个字符
				isNumber += 1;
			}
		}
	}

	@SuppressWarnings("deprecation")
	private void initalDesignColumnHeaderAndDetail(JasperDesign design,
			ReportDesignInfo config) throws JRException {
		JRDesignBand columnBand = new JRDesignBand();
		columnBand.setHeight(0);
		// columnBand.setHeight(ReportFieldInfo.TITLE_HEIGHT_DEFAULT_VALUE);
		columnBand.setSplitAllowed(true);
		isCrosstab = config.getCrosstabInfo().getRowGroupInfos().size() > 0;
		JRDesignBand detailBand = new JRDesignBand();
		if (!isCrosstab)
			detailBand.setHeight(ReportFieldInfo.FIELD_HEIGHT_DEFAULT_VALUE);
		detailBand.setSplitAllowed(true);

		List<ReportFieldInfo> sortList = (List<ReportFieldInfo>) config
				.getFileds();

		int x = 0;
		int width = 0;
		for (ReportFieldInfo field : sortList) {
			String key = field.getKey();

			if (key == null) {
				throw new JRException("The Filed key is null");
			}

			JRDesignField oneField = new JRDesignField();
			oneField.setName(key);
			oneField.setValueClassName(field.getClassName());
			design.addField(oneField);

			JRDesignStaticText staticText = new JRDesignStaticText();
			staticText.setX(x);
			staticText.setY(0);

			width = field.getWidth();
			// staticText.setWidth(width);
			staticText.setWidth(crosstabWidth / sortList.size());
			staticText.setHeight(field.getTitleHeight());
			// staticText.setForecolor(Color.white);
			// staticText.setBackcolor(new Color(0x33, 0x33, 0x33));
			staticText.setMode(JRElement.MODE_OPAQUE);

			byte lineBorder = 1;
			staticText.setBorder(lineBorder);
			staticText.setLeftBorder(lineBorder);
			staticText.setRightBorder(lineBorder);
			staticText.setTopBorder(lineBorder);
			staticText.setBottomBorder(lineBorder);

			staticText.setStyle(boldStyle);
			staticText.setText(field.getTitle());

			JRDesignTextField textField = new JRDesignTextField();
			textField.setX(x);
			textField.setY(0);
			textField.setWidth(width);
			textField.setHeight(field.getHeight());
			// textField.setBackcolor(new Color(0xC0, 0xC0, 0xC0));
			textField.setMode(JRElement.MODE_OPAQUE);
			textField.setHorizontalAlignment(JRAlignment.HORIZONTAL_ALIGN_LEFT);
			textField.setStyle(normalStyle);

			textField.setBorder(lineBorder);
			textField.setLeftBorder(lineBorder);
			textField.setRightBorder(lineBorder);
			textField.setTopBorder(lineBorder);
			textField.setBottomBorder(lineBorder);

			JRDesignExpression expression = new JRDesignExpression();

			expression.setValueClassName(field.getClassName());
			expression.setText(field.getExpress());

			textField.setExpression(expression);
			if (!isCrosstab) {
				detailBand.addElement(textField);
				columnBand.addElement(staticText);
			}

			x += width;
		}

		design.setColumnHeader(columnBand);
		design.setDetail(detailBand);
	}

	private void initalDesignColumnFooter(JasperDesign design,
			ReportDesignInfo config) throws JRException {
	}

	private void initalDesignPageFooter(JasperDesign design,
			ReportDesignInfo config) throws JRException {
	}

	private void initalDesignSummary(JasperDesign design,
			ReportDesignInfo config) throws JRException {

		JRDesignBand summaryBand = new JRDesignBand();
		summaryBand.setSplitAllowed(true);
		summaryBand.setHeight(200);
		
		if (isCrosstab) {
			this.initalDesignCrosstab(summaryBand, config);
		}
		this.initalDesignCharts(design, summaryBand, config);
		design.setSummary(summaryBand);
	}

	private void initalDesignCharts(JasperDesign design,
			JRDesignBand summaryBand, ReportDesignInfo config) {
		IType type = new Type();
		List<ChartsInfo> charts = config.getCharts();

		int height = 70;
		int width = 500;
		int x = 0;
		int y = 0;
		for (int i = 0; i < config.getCharts().size(); i++) {
			ChartsInfo chart = charts.get(i);
			JRDesignChart designChart = new JRDesignChart(design, type
					.getChartType(chart.getType()));
			if (chart.getHeight() != null) {
				height = Integer.parseInt(chart.getHeight());
			}
			if (chart.getWidth() != null) {
				width = Integer.parseInt(chart.getWidth());
			}
			if (chart.getX() != null) {
				x = Integer.parseInt(chart.getX());
			}
			if (chart.getY() != null) {
				y = Integer.parseInt(chart.getY());
			}
			designChart.setX(x);
			designChart.setY(y);
			designChart.setHeight(height);
			designChart.setWidth(width);
			// JRDesignExpression title = new JRDesignExpression();
			// title.addResourceChunk(charts.get(i).getTitle());
			// title.setValueClassName("java.lang.String");
			// designChart.setTitleExpression(title);
			// designChart.setTitleColor(new Color(255, 255, 0));
			// JRDesignLinePlot designLinePlot = (JRDesignLinePlot) designChart
			// .getPlot();
			// List color = new ArrayList();
			// color.add(newColor(255, 255, 0));
			// color.add(new Color(255, 0, 255));
			// designLinePlot.setSeriesColors(color);

			ITitanChartDataset chartDataset = new TitanChartDataset();
			designChart.setDataset(chartDataset.getDataset(chart));
			designChart.setLegendBackgroundColor(new Color(255, 255, 255));
			designChart.setLegendColor(new Color(0, 0, 0));

			if ("bar".equals(chart.getType())) {
				JRDesignBarPlot barPlot = (JRDesignBarPlot) designChart
						.getPlot();
				// barPlot.setShowLabels(true);
				barPlot.setShowTickLabels(true);
				barPlot.setShowTickMarks(true);
			}
			// JRDesignLinePlot
			// designLinePlot =
			// (JRDesignLinePlot)
			// designChart
			// .getPlot();

			// JRDesignExpression categoryTitle = new JRDesignExpression();
			// categoryTitle.addResourceChunk("hengzuobiao");
			// categoryTitle.setValueClassName("java.lang.Object"); //
			// designLinePlot.setCategoryAxisLabelExpression(categoryTitle);
			//		  
			// JRDesignExpression valueTitle = new JRDesignExpression();
			// valueTitle.addResourceChunk("hengzuobisdfsdfao");
			// valueTitle.setValueClassName("java.lang.Object"); //
			// designLinePlot.setCategoryAxisLabelExpression(valueTitle);

			summaryBand.addElement(designChart);
		}
	}

	private void initalDesignCrosstab(JRDesignBand summaryBand,
			ReportDesignInfo config) throws JRException {
		JRDesignCrosstab designCrosstab = new JRDesignCrosstab();
		designCrosstab.isRepeatColumnHeaders();
		designCrosstab.setKey("crosstab-1");
		designCrosstab.setWidth(crosstabWidth);
		designCrosstab.setHeight(118);
		// JRStyle style = new JRDesignStyle();
		// designCrosstab.setStyle(style);

		addCrosstabColumnGroup(designCrosstab, config);
		addCrosstabRowGroup(designCrosstab, config);
		setCrosstabHeader(designCrosstab, config);
		addCrosstabMeasure(designCrosstab, config);
		addCrosstabCells(designCrosstab, config);

		designCrosstab.setWhenNoDataCell(this.createCellContents(LINE_BORDER));

		summaryBand.addElement(designCrosstab);
	}

	private void addCrosstabMeasure(JRDesignCrosstab designCrosstab,
			ReportDesignInfo config) throws JRException {
		List<MeasureInfo> measureInfos = config.getCrosstabInfo()
				.getMeasureInfos();
		IType type = new Type();
		for (MeasureInfo measureInfo : measureInfos) {
			designCrosstab.addMeasure(this.createCrosstabmeasure(measureInfo
					.getVar(), measureInfo.getClazz(), "$F{"
					+ measureInfo.getFiled() + "}", type
					.getFunctionType(measureInfo.getFunctioin())));
		}
	}

	private void addCrosstabRowGroup(JRDesignCrosstab designCrosstab,
			ReportDesignInfo config) throws JRException {
		List<RowGroupInfo> rowGroupInfos = config.getCrosstabInfo()
				.getRowGroupInfos();
		for (RowGroupInfo rowGroupInfo : rowGroupInfos) {
			this.addCrosstabRowGroup(designCrosstab, rowGroupInfo.getFiled(),
					rowGroupInfo.getClazz(), rowGroupInfo.getFiled(),
					rowGroupInfo.getTotalHeader(), Integer
							.parseInt(rowGroupInfo.getWidth()), Integer
							.parseInt(rowGroupInfo.getHeight()));
			// this.addCrosstabRowGroup(designCrosstab, "STATION", String.class
			// .getName(), "STATION", "合计1", secnodRowWidth, 30);
		}
	}

	private void addCrosstabColumnGroup(JRDesignCrosstab designCrosstab,
			ReportDesignInfo config) throws JRException {
		List<ColumnGroupInfo> columnGroupInfos = config.getCrosstabInfo()
				.getColumnGroupInfos();
		for (ColumnGroupInfo columnGroupInfo : columnGroupInfos) {
			this.addCrosstabColumnGroup(designCrosstab, columnGroupInfo
					.getFiled(), columnGroupInfo.getClazz(), columnGroupInfo
					.getFiled(), columnGroupInfo.getTotalHeader(), Integer
					.parseInt(columnGroupInfo.getWidth()), Integer
					.parseInt(columnGroupInfo.getHeight()));
			// this.addCrosstabColumnGroup(designCrosstab, "MONTH", String.class
			// .getName(), "MONTH", "合计", 50, 30);
		}
	}

	@SuppressWarnings("unchecked")
	private void addCrosstabCells(JRDesignCrosstab designCrosstab,
			ReportDesignInfo config) throws JRException {

		List<CellInfo> cellInfos = config.getCrosstabInfo().getCellInfos();
		String measureVar = null;

		if (cellInfos != null && !cellInfos.isEmpty()) {
			for (CellInfo cellInfo : cellInfos) {
				measureVar = "$V{" + cellInfo.getMeasureVar() + "}";

				this.addCrosstabCell(designCrosstab, cellInfo.getClazz(),
						measureVar, cellInfo.getRowGroup(), cellInfo
								.getColumnGroup(), cellInfo.getFont(), Integer
								.parseInt(cellInfo.getWidth()), Integer
								.parseInt(cellInfo.getHeight()));
			}

			return;
		}

		JRDesignCrosstabMeasure measureInfo = (JRDesignCrosstabMeasure) designCrosstab
				.getMesuresList().get(0);

		measureVar = "$V{" + measureInfo.getName() + "}";
		String className = measureInfo.getValueClassName();

		List<JRDesignCrosstabRowGroup> rowGroups = designCrosstab
				.getRowGroupsList();
		List<JRDesignCrosstabColumnGroup> columnGroups = designCrosstab
				.getColumnGroupsList();

		if (rowGroups != null && columnGroups != null) {
			int height = 30;
			int width = 50;

			if (!rowGroups.isEmpty()) {
				JRDesignCrosstabRowGroup crosstabRowGroup = (JRDesignCrosstabRowGroup) rowGroups
						.get(0);
				height = crosstabRowGroup.getHeader().getElements()[0]
						.getHeight();
				width = crosstabRowGroup.getHeader().getElements()[0]
						.getWidth();
			}

			this.addCrosstabCell(designCrosstab, className, measureVar, null,
					null, null, width, height);

			for (JRDesignCrosstabRowGroup rowGroup : rowGroups) {
				this.addCrosstabCell(designCrosstab, className, measureVar,
						rowGroup.getName(), null, FONT_BLOD, width, height);

				for (JRDesignCrosstabColumnGroup columnGroup : columnGroups) {

					this.addCrosstabCell(designCrosstab, className, measureVar,
							rowGroup.getName(), columnGroup.getName(),
							FONT_BLOD, width, height);
				}
			}

			for (JRDesignCrosstabColumnGroup columnGroup : columnGroups) {
				this.addCrosstabCell(designCrosstab, className, measureVar,
						null, columnGroup.getName(), FONT_BLOD, width, height);
			}
		}

	}

	private void setCrosstabHeader(JRDesignCrosstab designCrosstab,
			ReportDesignInfo config) {
		JRDesignCellContents headerCell = this.createCellContents(LINE_BORDER);

		JRCrosstabColumnGroup[] columnGroups = designCrosstab.getColumnGroups();
		JRCrosstabRowGroup[] rowGroups = designCrosstab.getRowGroups();
		//通过行列数计算划线的位置
	
		if (columnGroups.length == 1 && rowGroups.length == 3){
			int firstRowWidth = rowGroups[0].getWidth();
			int secondRowWidth = rowGroups[1].getWidth();
			int thirdRowWidth = rowGroups[2].getWidth();
			
			int firstColumnHeight = columnGroups[0].getHeight();
			

			JRDesignLine firstLine = new JRDesignLine();
			JRDesignLine secondLine = new JRDesignLine();

			headerCell.addElement(firstLine);
			headerCell.addElement(secondLine);

			firstLine.getLinePen().setLineWidth(LINE_BORDER);
			firstLine.setDirection(JRDesignLine.DIRECTION_TOP_DOWN);
			firstLine.setX(0);
			firstLine.setY(0);
			firstLine.setWidth(firstRowWidth);
			firstLine.setHeight(firstColumnHeight);
			firstLine.setStretchType(JRDesignLine.STRETCH_TYPE_NO_STRETCH);

			secondLine.setDirection(JRDesignLine.DIRECTION_TOP_DOWN);
			secondLine.getLinePen().setLineWidth(LINE_BORDER);
			secondLine.setX(0);
			secondLine.setY(0);
			secondLine.setWidth(firstRowWidth + secondRowWidth + thirdRowWidth);
			secondLine.setHeight(firstColumnHeight);
			secondLine.setStretchType(JRDesignLine.STRETCH_TYPE_NO_STRETCH);
			
		} else if (columnGroups.length > 1 && rowGroups.length > 1) {

			int firstRowWidth = rowGroups[0].getWidth();
			int secondRowWidth = rowGroups[1].getWidth();
			int firstColumnHeight = columnGroups[0].getHeight();
			int secondColumnHeight = columnGroups[1].getHeight();

			JRDesignLine firstLine = new JRDesignLine();
			JRDesignLine secondLine = new JRDesignLine();

			headerCell.addElement(firstLine);
			headerCell.addElement(secondLine);

			firstLine.getLinePen().setLineWidth(LINE_BORDER);
			firstLine.setDirection(JRDesignLine.DIRECTION_TOP_DOWN);
			firstLine.setX(0);
			firstLine.setY(0);
			firstLine.setWidth(firstRowWidth);
			firstLine.setHeight(firstColumnHeight + secondColumnHeight);
			firstLine.setStretchType(JRDesignLine.STRETCH_TYPE_NO_STRETCH);

			secondLine.setDirection(JRDesignLine.DIRECTION_TOP_DOWN);
			secondLine.getLinePen().setLineWidth(LINE_BORDER);
			secondLine.setX(0);
			secondLine.setY(0);
			secondLine.setWidth(firstRowWidth + secondRowWidth);
			secondLine.setHeight(firstColumnHeight + secondColumnHeight);
			secondLine.setStretchType(JRDesignLine.STRETCH_TYPE_NO_STRETCH);
		} else if (columnGroups.length > 1 && rowGroups.length == 1) {
			int firstRowWidth = rowGroups[0].getWidth();
			// int secondRowWidth = rowGroups[1].getWidth();
			int firstColumnHeight = columnGroups[0].getHeight();
			int secondColumnHeight = columnGroups[1].getHeight();

			JRDesignLine firstLine = new JRDesignLine();
			JRDesignLine secondLine = new JRDesignLine();

			headerCell.addElement(firstLine);
			headerCell.addElement(secondLine);

			firstLine.getLinePen().setLineWidth(LINE_BORDER);
			firstLine.setDirection(JRDesignLine.DIRECTION_TOP_DOWN);
			firstLine.setX(0);
			firstLine.setY(0);
			firstLine.setWidth(firstRowWidth);
			firstLine.setHeight(firstColumnHeight + secondColumnHeight);
			firstLine.setStretchType(JRDesignLine.STRETCH_TYPE_NO_STRETCH);

			secondLine.setDirection(JRDesignLine.DIRECTION_TOP_DOWN);
			secondLine.getLinePen().setLineWidth(LINE_BORDER);
			secondLine.setX(0);
			secondLine.setY(0);
			secondLine.setWidth(firstRowWidth);
			secondLine.setHeight(firstColumnHeight + secondColumnHeight);
			secondLine.setStretchType(JRDesignLine.STRETCH_TYPE_NO_STRETCH);
		} else if (columnGroups.length == 1 && rowGroups.length > 1) {

			int firstRowWidth = rowGroups[0].getWidth();
			int secondRowWidth = rowGroups[1].getWidth();
			int firstColumnHeight = columnGroups[0].getHeight();
		//	int secondColumnHeight = columnGroups[1].getHeight();

			JRDesignLine firstLine = new JRDesignLine();
			JRDesignLine secondLine = new JRDesignLine();

			headerCell.addElement(firstLine);
			headerCell.addElement(secondLine);

			firstLine.getLinePen().setLineWidth(LINE_BORDER);
			firstLine.setDirection(JRDesignLine.DIRECTION_TOP_DOWN);
			firstLine.setX(0);
			firstLine.setY(0);
			firstLine.setWidth(firstRowWidth);
			firstLine.setHeight(firstColumnHeight );
			firstLine.setStretchType(JRDesignLine.STRETCH_TYPE_NO_STRETCH);

			secondLine.setDirection(JRDesignLine.DIRECTION_TOP_DOWN);
			secondLine.getLinePen().setLineWidth(LINE_BORDER);
			secondLine.setX(0);
			secondLine.setY(0);
			secondLine.setWidth(firstRowWidth + secondRowWidth);
			secondLine.setHeight(firstColumnHeight );
			secondLine.setStretchType(JRDesignLine.STRETCH_TYPE_NO_STRETCH);
		} else if (columnGroups.length == 1 && rowGroups.length == 1) {
			int firstRowWidth = rowGroups[0].getWidth();
			// int secondRowWidth = rowGroups[1].getWidth();
			int firstColumnHeight = columnGroups[0].getHeight();
			// int secondColumnHeight = columnGroups[1].getHeight();

			// JRDesignLine firstLine = new JRDesignLine();
			JRDesignLine secondLine = new JRDesignLine();

			// headerCell.addElement(firstLine);
			headerCell.addElement(secondLine);

			// firstLine.getLinePen().setLineWidth(LINE_BORDER);
			// firstLine.setDirection(JRDesignLine.DIRECTION_TOP_DOWN);
			// firstLine.setX(0);
			// firstLine.setY(0);
			// firstLine.setWidth(firstRowWidth);
			// firstLine.setHeight(firstColumnHeight );
			// firstLine.setStretchType(JRDesignLine.STRETCH_TYPE_NO_STRETCH);

			secondLine.setDirection(JRDesignLine.DIRECTION_TOP_DOWN);
			secondLine.getLinePen().setLineWidth(LINE_BORDER);
			secondLine.setX(0);
			secondLine.setY(0);
			secondLine.setWidth(firstRowWidth);
			secondLine.setHeight(firstColumnHeight);
			secondLine.setStretchType(JRDesignLine.STRETCH_TYPE_NO_STRETCH);
		}

		CrosstabInfo crosstabInfo = config.getCrosstabInfo();
		String[] headers = crosstabInfo.getHeader().split(",");
		int firstRowWidth = 0;
		if (columnGroups.length > 0)
			firstRowWidth = rowGroups[0].getWidth();
		int secondRowWidth = 0;
		if (rowGroups.length == 2) {
			secondRowWidth = rowGroups[1].getWidth();
		}
		int firstColumnHeight = 0;
		if (columnGroups.length > 0)
			firstColumnHeight = columnGroups[0].getHeight();
		int secondColumnHeight = 0;
		if (columnGroups.length == 2) {
			secondColumnHeight = columnGroups[1].getHeight();
		}
		int[] x = { 0, firstRowWidth - 6, firstRowWidth / 2 + 16 };
		int[] y = { firstColumnHeight + secondColumnHeight - 26,
				firstColumnHeight + secondColumnHeight - 20, 0 };
		// int[] x = { 0, 0, 0 };
		// int[] y = { 0, 0, 0 };
		//TODO:xml 是输出的是word格式的报表
		if("pdf".equals(this.reportType) || "xml".equals(this.reportType)){
		for (int i = 0; i < headers.length; i++) {
			JRDesignStaticText staticText = new JRDesignStaticText();
			
			staticText.setX(x[i]);
			staticText.setY(y[i]);
			//staticText.setWidth(firstRowWidth + secondRowWidth - x[i] - 1);
			if(rowGroups.length == 3){
				staticText.setWidth(firstRowWidth + secondRowWidth  - 1);
			} else {
				staticText.setWidth(firstRowWidth + secondRowWidth - x[i] - 1);
			}
			staticText.setHeight(firstColumnHeight + secondColumnHeight - y[i]
					- 1);
			staticText.setMode(JRElement.MODE_TRANSPARENT);
			staticText.setStyle(boldStyle);
			staticText.setText(headers[i]);
			headerCell.addElement(staticText);
		}
		} else {
			JRDesignStaticText staticText = new JRDesignStaticText();

			staticText.setX(0);
			staticText.setY(0);
			staticText.setWidth(firstRowWidth + secondRowWidth - x[0] - 1);
			staticText.setHeight(20);
			staticText.setMode(JRElement.MODE_TRANSPARENT);
			staticText.setStyle(boldStyle);
			staticText.setText(headers[0]);
			headerCell.addElement(staticText);
		}
		// for (String header : headers) {
		// JRDesignStaticText staticText = new JRDesignStaticText();
		//
		// staticText.setX(0);
		// staticText.setY(15);
		// staticText.setWidth(40);
		// staticText.setHeight(25);
		// staticText.setMode(JRElement.MODE_TRANSPARENT);
		// staticText.setStyle(boldStyle);
		// staticText.setText(header);
		// headerCell.addElement(staticText);
		// }

		designCrosstab.setHeaderCell(headerCell);
	}

	@SuppressWarnings("unchecked")
	private void addCrosstabCell(JRDesignCrosstab designCrosstab,
			String className, String express, String rowTotalGroup,
			String columnTotalGroup, String fontSytle, int width, int height)
			throws JRException {

		JRDesignCrosstabCell cell = new JRDesignCrosstabCell();

		cell.setContents(this.createCrosstabCellContents(className, express,
				fontSytle, width, height));
		cell.setHeight(height);
		cell.setWidth(width);

		if (rowTotalGroup != null) {
			cell.setRowTotalGroup(rowTotalGroup);

			List rowGroups = designCrosstab.getRowGroupsList();
			if (!rowGroups.isEmpty()) {
				JRCrosstabRowGroup group = (JRDesignCrosstabRowGroup) rowGroups
						.get(0);

				if (rowTotalGroup.equals(group.getName())) {
					cell.getContents().getLineBox().getBottomPen()
							.setLineWidth(LINE_BORDER);
					cell.getContents().getLineBox().getBottomPen()
							.setLineColor(new Color(0x000000));
					cell.getContents().getLineBox().getBottomPen()
							.setLineStyle(JRLine.PEN_THIN);
				}
			}
		}
		// JRVerifier
		if (columnTotalGroup != null) {
			cell.setColumnTotalGroup(columnTotalGroup);

			List columnGroups = designCrosstab.getColumnGroupsList();
			if (!columnGroups.isEmpty()) {
				JRDesignCrosstabColumnGroup group = (JRDesignCrosstabColumnGroup) columnGroups
						.get(0);

				if (columnTotalGroup.equals(group.getName())) {
					cell.getContents().getLineBox().getRightPen().setLineWidth(
							LINE_BORDER);

					cell
							.setWidth(group.getHeader().getElements()[0]
									.getWidth());
				} else {
					if (columnGroups.size() > 1) {
						JRDesignCrosstabColumnGroup group2 = (JRDesignCrosstabColumnGroup) columnGroups
								.get(1);

						cell.setWidth(group2.getHeader().getElements()[0]
								.getWidth());
					}
				}
			}
		}

		designCrosstab.addCell(cell);
	}

	private JRDesignCrosstabMeasure createCrosstabmeasure(String name,
			String className, String express, byte type) {

		JRDesignCrosstabMeasure measure = new JRDesignCrosstabMeasure();
		measure.setName(name);
		measure.setValueClassName(className);
		measure.setCalculation(type);

		JRDesignExpression expression = new JRDesignExpression();
		expression.setValueClassName(className);
		expression.setText(express);

		measure.setValueExpression(expression);

		return measure;
	}

	private void addCrosstabRowGroup(JRDesignCrosstab designCrosstab,
			String name, String className, String express, String totalExpress,
			int width, int height) throws JRException {

		JRDesignCrosstabRowGroup rowGroup = new JRDesignCrosstabRowGroup();
		this.initalCrosstabGroup(rowGroup, name, className, express,
				totalExpress, width, height);

		if (designCrosstab.getRowGroupsList().isEmpty()) {
			JRCellContents totalHeader = rowGroup.getTotalHeader();

			if (totalHeader != null) {
				totalHeader.getLineBox().getBottomPen().setLineWidth(
						LINE_BORDER);
			}
		}
		rowGroup.setWidth(width);

		designCrosstab.addRowGroup(rowGroup);
	}

	private void addCrosstabColumnGroup(JRDesignCrosstab designCrosstab,
			String name, String className, String express, String totalExpress,
			int width, int height) throws JRException {

		JRDesignCrosstabColumnGroup columnGroup = new JRDesignCrosstabColumnGroup();
		this.initalCrosstabGroup(columnGroup, name, className, express,
				totalExpress, width, height);

		columnGroup.setHeight(height);

		if (designCrosstab.getColumnGroupsList().isEmpty()) {
			JRCellContents totalHeader = columnGroup.getTotalHeader();

			if (totalHeader != null) {
				totalHeader.getLineBox().getRightPen()
						.setLineWidth(LINE_BORDER);
			}
		}
		designCrosstab.addColumnGroup(columnGroup);
	}

	private void initalCrosstabGroup(JRDesignCrosstabGroup group, String name,
			String className, String express, String totalExpress, int width,
			int height) {

		group.setName(name);
		group.setBucket(this.createCrosstabBucket(String.class.getName(), "$F{"
				+ express + "}"));
		group.setTotalPosition(BucketDefinition.TOTAL_POSITION_END);

		group.setHeader(this.createCrosstabCellContents(className, "$V{"
				+ express + "}", null, width, height));

		if (totalExpress != null && !totalExpress.trim().equals("")) {
			group.setTotalHeader(this.createCrosstabStaticCellContents(
					String.class.getName(), totalExpress, width, height));
		}
	}

	// private JRDesignCellContents createCrosstabCellContents(String className,
	// String express, String fontStyle, int width, int height) {
	//		
	// }
	private JRDesignCellContents createCrosstabCellContents(String className,
			String express, String fontStyle, int width, int height) {

		JRDesignCellContents headerCellContents = this
				.createCellContents(LINE_BORDER);

		if (express != null && !"$V{}".equals(express.trim())) {
			JRDesignTextField textField = new JRDesignTextField();
			if ("java.lang.Double".equals(className)
					|| "java.lang.Float".equals(className)) {
				textField.setPattern("#,##0.00");
			}
			if ("java.lang.Integer".equals(className)
					|| "java.lang.Long".equals(className)) {
				textField.setPattern("#,##0");
			}
			textField.setX(0);
			textField.setY(0);

			textField.setWidth(width);
			textField.setHeight(height);
			textField.setMode(JRElement.MODE_TRANSPARENT);
			textField.setHorizontalAlignment(JRAlignment.HORIZONTAL_ALIGN_LEFT);

			if (FONT_BLOD.equalsIgnoreCase(fontStyle)) {
				textField.setStyle(boldStyle);
			} else if (FONT_ITALIC.equalsIgnoreCase(fontStyle)) {
				textField.setStyle(italicStyle);
			} else {
				textField.setStyle(normalStyle);
			}

			JRDesignExpression expression = new JRDesignExpression();
			expression.setValueClassName(className);
			if (sort != null && express.indexOf(sort) > 0)
				expression.setText(express + ".substring(8)");
			else
				expression.setText(express);
			// expression.
			textField.setExpression(expression);

			headerCellContents.addElement(textField);
		}

		return headerCellContents;
	}

	private void setBoxLineTopAndLeft(JRLineBox lineBox, float total) {
		// TODO:update
		this.setBoxLine(lineBox, total, total, total, total);

		// this.setBoxLine(lineBox, total, 0, total, 0);
	}

	private void setBoxLine(JRLineBox lineBox, float top, float bottom,
			float left, float right) {

		lineBox.getBottomPen().setLineWidth(bottom);
		lineBox.getTopPen().setLineWidth(top);
		lineBox.getRightPen().setLineWidth(right);
		lineBox.getLeftPen().setLineWidth(left);
	}

	private JRDesignCellContents createCrosstabStaticCellContents(
			String className, String express, int width, int height) {

		JRDesignCellContents headerCellContents = this
				.createCellContents(LINE_BORDER);

		JRDesignStaticText staticText = new JRDesignStaticText();

		staticText.setX(0);
		staticText.setY(0);
		staticText.setWidth(width);
		staticText.setHeight(height);
		staticText.setMode(JRElement.MODE_TRANSPARENT);
		staticText.setStyle(boldStyle);
		staticText.setText(express);

		headerCellContents.addElement(staticText);

		return headerCellContents;
	}

	private JRDesignCellContents createCellContents(float lineBorder) {
		JRDesignCellContents cellContents = new JRDesignCellContents();
		cellContents.setMode(JRElement.MODE_TRANSPARENT);

		if (lineBorder > 0) {
			this.setBoxLineTopAndLeft(cellContents.getLineBox(), lineBorder);
		}
		return cellContents;
	}

	private JRDesignCrosstabBucket createCrosstabBucket(String className,
			String express) {
		JRDesignCrosstabBucket bucket = new JRDesignCrosstabBucket();
		JRDesignExpression expression = new JRDesignExpression();
		expression.setValueClassName(className);
		if (sort != null && express.indexOf(sort) > 0)
			if (sortField == null)
				expression.setText("$F{number}+" + express);
			else
				expression.setText("$F{" + sortField + "}+" + express);
		else
			expression.setText(express);
		bucket.setExpression(expression);
		return bucket;
	}
}
